package com.hamilton.erik.pt.core.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.hamilton.erik.pt.core.dao.AnimalDAO;
import com.hamilton.erik.pt.core.db.H2JdbcAccess;
import com.hamilton.erik.pt.core.model.Animal;
import com.hamilton.erik.pt.core.util.SqlUtil;

public class H2AnimalDAO implements AnimalDAO {
	
	private final String ANIMAL_DB_TABLE = "APPLICATION.ANIMAL";
	
	private final String INSERT_ANIMAL = 
			String.format(
				"INSERT INTO %s (USER_NAME, ANIMAL_TYPE, GENUS, SPECIES, " +
				"NAME, BIRTH_DATE_STRING, PURCHASE_DATE_STRING, GENDER) " +
				"VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
				ANIMAL_DB_TABLE);
	
	private final String UPDATE_ANIMAL =
			String.format(
				"UPDATE %s SET ANIMAL_TYPE=?, GENUS=?, SPECIES=?, " +
				"NAME=?, BIRTH_DATE_STRING=?, PURCHASE_DATE_STRING=?, " +
				"GENDER=? WHERE ID=?",
				ANIMAL_DB_TABLE);
	
	private final String DELETE_ANIMAL =
			String.format("DELETE FROM %s WHERE ID=?", ANIMAL_DB_TABLE);
	
	private final String GET_ALL_ANIMALS =
			String.format(
				"SELECT * FROM %s WHERE USER_NAME = ?", ANIMAL_DB_TABLE);
	
	private final String DELETE_ALL_ANIMALS =
			String.format("DELETE FROM %s WHERE USER_NAME=?", ANIMAL_DB_TABLE);

	@Override
	public int insertAnimal(Animal animal) throws SQLException {

		int insertedRow = -1;
		Connection conn = null;
		
		try {
			conn = H2JdbcAccess.getInstance().getConnection();
			conn.setAutoCommit(false);
						
			PreparedStatement stmt = conn.prepareStatement(INSERT_ANIMAL);
		
			stmt.setString(1, animal.getUserName());
			stmt.setString(2, animal.getType());
			SqlUtil.setStringOrNull(3, stmt, animal.getGenus());
			SqlUtil.setStringOrNull(4, stmt, animal.getSpecies());
			stmt.setString(5, animal.getName());
			SqlUtil.setStringOrNull(6, stmt, animal.getBirthDate());
			SqlUtil.setStringOrNull(7, stmt, animal.getPurchaseDate());
			stmt.setString(8, animal.getGender().toString());
			
			insertedRow = stmt.executeUpdate();
			
			conn.commit();

			return insertedRow;
		} catch (SQLException e) {
			throw e;
		} finally {
			if(conn != null) try { conn.close(); } catch (Exception ignore) {}
		}
	}

	@Override
	public boolean deleteAnimal(Long animalId) throws SQLException {

		int returnValue = -1;
		Connection conn = null;
		
		try {
			conn = H2JdbcAccess.getInstance().getConnection();
			conn.setAutoCommit(false);
						
			PreparedStatement stmt = conn.prepareStatement(DELETE_ANIMAL);

			stmt.setLong(1, animalId);
			
			returnValue = stmt.executeUpdate();
			
			conn.commit();

			if(returnValue > 0) {
				return true;
			}
		} catch (SQLException e) {
			throw e;
		} finally {
			if(conn != null) try { conn.close(); } catch (Exception ignore) {}
		}
		
		return false;
	}
	
	@Override
	public Animal findAnimal(Long id) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int updateAnimal(Animal animal) throws SQLException {

		int updatedRow = -1;
		Connection conn = null;
		
		try {
			conn = H2JdbcAccess.getInstance().getConnection();
			conn.setAutoCommit(false);
						
			PreparedStatement stmt = conn.prepareStatement(UPDATE_ANIMAL);

			stmt.setString(1, animal.getType());
			SqlUtil.setStringOrNull(2, stmt, animal.getGenus());
			SqlUtil.setStringOrNull(3, stmt, animal.getSpecies());
			stmt.setString(4, animal.getName());
			SqlUtil.setStringOrNull(5, stmt, animal.getBirthDate());
			SqlUtil.setStringOrNull(6, stmt, animal.getPurchaseDate());
			stmt.setString(7, animal.getGender().toString());
			stmt.setLong(8, animal.getId());
			
			updatedRow = stmt.executeUpdate();
			
			conn.commit();

			return updatedRow;
		} catch (SQLException e) {
			throw e;
		} finally {
			if(conn != null) try { conn.close(); } catch (Exception ignore) {}
		}
	}

	@Override
	public List<Animal> getAllAnimals(String userName) throws SQLException {

		List<Animal> animals = new ArrayList<Animal>();
		Connection conn = null;
		
		try {
			conn = H2JdbcAccess.getInstance().getConnection();
						
			PreparedStatement stmt = conn.prepareStatement(GET_ALL_ANIMALS);
		
			stmt.setString(1, userName);
			
			ResultSet rs = stmt.executeQuery();
			
			while(rs.next()) {
				Animal newAnimal = new Animal();
	
				newAnimal.setId(rs.getLong(1));
				newAnimal.setUserName(rs.getString(2));
				newAnimal.setType(rs.getString(3));
				newAnimal.setGenus(rs.getString(4));
				newAnimal.setSpecies(rs.getString(5));
				newAnimal.setName(rs.getString(6));
				newAnimal.setBirthDate(rs.getString(7));
				newAnimal.setPurchaseDate(rs.getString(8));
				newAnimal.setGender(rs.getString(9));
				
				animals.add(newAnimal);
			}
			
			return animals;
			
		} catch (SQLException e) {
			throw e;
		} finally {
			if(conn != null) try { conn.close(); } catch (Exception ignore) {}
		}
	}

	@Override
	public boolean deleteAllAnimals(String userName) throws SQLException {

		int returnValue = -1;
		Connection conn = null;
		
		try {
			conn = H2JdbcAccess.getInstance().getConnection();
			conn.setAutoCommit(false);
						
			PreparedStatement stmt = conn.prepareStatement(DELETE_ALL_ANIMALS);

			stmt.setString(1, userName);
			
			returnValue = stmt.executeUpdate();
			
			conn.commit();

			if(returnValue > 0) {
				return true;
			}
		} catch (SQLException e) {
			throw e;
		} finally {
			if(conn != null) try { conn.close(); } catch (Exception ignore) {}
		}
		
		return false;
	}

}
